home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part08 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  38.9 KB

  1. Subject:  v18i030:  Mail user's shell version 6.4, Part08/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 30
  8. Archive-name: mush6.4/part08
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 8 (of 19)."
  19. # Contents:  misc.c setopts.c
  20. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:14 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'misc.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'misc.c'\"
  24. else
  25. echo shar: Extracting \"'misc.c'\" \(18158 characters\)
  26. sed "s/^X//" >'misc.c' <<'END_OF_FILE'
  27. X/* @(#)misc.c    (c) copyright 10/18/86 (Dan Heller) */
  28. X
  29. X#include "mush.h"
  30. X
  31. X/* check to see if a string describes a message that is within the range of
  32. X * all messages; if invalid, return 0 and print error. else return msg number
  33. X */
  34. Xchk_msg(s)
  35. Xregister char *s;
  36. X{
  37. X    register int n;
  38. X
  39. X    if ((n = atoi(s)) > 0 && n <= msg_cnt)
  40. X    return n;
  41. X    else if (*s == '^' && msg_cnt)
  42. X    return 1;
  43. X    else if (*s == '$' && msg_cnt)
  44. X    return msg_cnt;
  45. X    else if (*s == '.' && msg_cnt)
  46. X    return current_msg+1;
  47. X    print("Invalid message number: %s\n", s);
  48. X    return 0;
  49. X}
  50. X
  51. X/*
  52. X * loop thru all msgs starting with current_msg and find next undeleted and
  53. X * unsaved message.  If the variable "wrap" is set, wrap to the beginning of
  54. X * the message list if we hit the end.  otherwise, stop at the end of the list.
  55. X */
  56. Xnext_msg()
  57. X{
  58. X    register int n = current_msg;
  59. X    register int wrap = !!do_set(set_options, "wrap");
  60. X
  61. X    if (!msg_cnt)
  62. X    return current_msg = 0;
  63. X    for (n++; n != current_msg; n++)
  64. X    if (n == msg_cnt)     /* hit the end, start back at the beginning */
  65. X        if (!wrap)
  66. X        return current_msg;
  67. X        else
  68. X        n = -1; /* increments to 0 in  loop  */
  69. X    else if (isoff(msg[n].m_flags, DELETE) &&
  70. X         isoff(msg[n].m_flags, SAVED))
  71. X        return current_msg = n;
  72. X    return current_msg = 0;
  73. X}
  74. X
  75. X/* since print_help just prints help, always return help() */
  76. Xprint_help(argc, argv)
  77. Xregister char **argv;
  78. X{
  79. X#ifdef SUNTOOL
  80. X    if (istool)
  81. X    return help(tool->tl_windowfd, "general", tool_help);
  82. X#endif /* SUNTOOL */
  83. X    if (!argc || !*++argv)
  84. X    return help(0, "general", cmd_help);
  85. X    return help(0, *argv, cmd_help);
  86. X}
  87. X
  88. X/* since this function does not affect messages, return -1 */
  89. Xhelp(fd, str, file)
  90. X#ifdef SUNTOOL
  91. Xcaddr_t *str;
  92. X#else
  93. Xchar *str;
  94. X#endif /* SUNTOOL */
  95. Xchar *file;
  96. X{
  97. X#ifdef SUNTOOL
  98. X    if (istool > 1) {
  99. X    int oldmask;
  100. X    if (!fd)
  101. X        fd = print_sw->ts_windowfd;
  102. X    oldmask = sigblock(1 << ((SIGALRM) - 1));
  103. X    lock_cursors();
  104. X    if (display_help(fd, str, file, fonts[LARGE]) && file)
  105. X        error("can't read %s", file);
  106. X    unlock_cursors();
  107. X    (void) sigsetmask(oldmask);
  108. X    } else
  109. X#endif /* SUNTOOL */
  110. X    if (find_help(str, file) && file)
  111. X    error("can't read %s", file);
  112. X    return 0; /* doesn't affect any messages */
  113. X}
  114. X
  115. X#ifdef SUNTOOL
  116. Xvoid
  117. Xunlock_cursors()
  118. X{
  119. X    if (istool < 2)
  120. X    return;
  121. X    win_setcursor(print_sw->ts_windowfd, &main_cursor);
  122. X    win_setcursor(panel_sw->ts_windowfd, &main_cursor);
  123. X    if (getting_opts)
  124. X    win_setcursor(msg_sw->ts_windowfd, &checkmark);
  125. X    else if (ison(glob_flags, IS_GETTING))
  126. X    win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  127. X    else
  128. X    win_setcursor(msg_sw->ts_windowfd, &read_cursor);
  129. X    win_setcursor(hdr_panel_sw->ts_windowfd, &main_cursor);
  130. X    win_setcursor(hdr_sw->ts_windowfd, &l_cursor);
  131. X}
  132. X
  133. Xvoid
  134. Xlock_cursors()
  135. X{
  136. X    if (istool < 2)
  137. X    return;
  138. X    win_setcursor(hdr_sw->ts_windowfd, &coffee);
  139. X    win_setcursor(print_sw->ts_windowfd, &coffee);
  140. X    win_setcursor(panel_sw->ts_windowfd, &coffee);
  141. X    win_setcursor(msg_sw->ts_windowfd, &coffee);
  142. X    win_setcursor(hdr_panel_sw->ts_windowfd, &coffee);
  143. X}
  144. X
  145. X#include <suntool/fullscreen.h>
  146. X/* return the event-id that confirmed */
  147. Xconfirm(fd)
  148. X{
  149. X    struct fullscreen *fs;
  150. X
  151. X    struct inputmask im;
  152. X    struct inputevent event;
  153. X
  154. X    fs = fullscreen_init(fd);
  155. X    input_imnull(&im);
  156. X    im.im_flags |= IM_ASCII;
  157. X    win_setinputcodebit(&im, MS_LEFT);
  158. X    win_setinputcodebit(&im, MS_MIDDLE);
  159. X    win_setinputcodebit(&im, MS_RIGHT);
  160. X    win_setinputmask(fd, &im, &im, WIN_NULLLINK);
  161. X    win_setcursor(fd, &l_cursor);
  162. X    if (input_readevent(fd, &event) == -1)
  163. X    error("confirm failed");
  164. X    fullscreen_destroy(fs);
  165. X    return ID;
  166. X}
  167. X#endif /* SUNTOOL */
  168. X
  169. X/* return -1 on error or number of arguments in argv that were parsed */
  170. Xget_msg_list(argv, list)
  171. Xregister char **argv;
  172. Xchar list[];
  173. X{
  174. X    register char *p2, *p, *end, ch;
  175. X    char buf[BUFSIZ];
  176. X    register int n;
  177. X
  178. X    if (!msg_cnt) {
  179. X    print("No messages.\n");
  180. X    return -1;
  181. X    }
  182. X    if (!argv || !*argv) {
  183. X    if (isoff(glob_flags, IS_PIPE))
  184. X        set_msg_bit(list, current_msg);
  185. X    return 0;
  186. X    }
  187. X    /* first, stuff argv's args into a single char array buffer */
  188. X    (void) argv_to_string(buf, argv);
  189. X    p = buf;
  190. X
  191. X    Debug("get_msg_list: parsing: (%s): ", p);
  192. X    /* find the end of the message list */
  193. X    skipmsglist(0);
  194. X    end = p;
  195. X    while (*end && end != buf && !isspace(*end))
  196. X    --end;
  197. X    ch = *end, *end = '\0'; /* temporarily plug with nul */
  198. X    p = buf; /* reset to the beginning */
  199. X    /*
  200. X     * if do_range returns NULL, an invalid message was specified
  201. X     */
  202. X    if (!(p2 = do_range(p, list))) {
  203. X    *end = ch; /* just in case */
  204. X    return -1;
  205. X    }
  206. X    /*
  207. X     * if p2 == p (and p isn't $ or ^ or .), then no message list was
  208. X     * specified.  set the current message in such cases if we're not piping
  209. X     */
  210. X    if (p2 == p) {
  211. X    if (*p == '$')
  212. X        set_msg_bit(list, msg_cnt-1);
  213. X    else if (*p == '^')
  214. X        set_msg_bit(list, 0);
  215. X    else if (*p == '.' || isoff(glob_flags, IS_PIPE))
  216. X        set_msg_bit(list, current_msg);
  217. X    }
  218. X    for (n = 0; p2 > p && *argv; n++)
  219. X    p2 -= (strlen(*argv++)+1);
  220. X    Debug("parsed %d args\n", n);
  221. X    *end = ch;
  222. X    return n;
  223. X}
  224. X
  225. X/*
  226. X * execute a command from a string.  f'rinstance: "pick -f foobar"
  227. X * The string is made into an argv and then run.  Errors are printed
  228. X * if the command failed to make.
  229. X *   NOTES:
  230. X *     NEVER pass straight text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...")
  231. X *     no history is expanded (ignore_bang).
  232. X */
  233. Xcmd_line(buf, list)
  234. Xchar buf[], list[];
  235. X{
  236. X    register char **argv;
  237. X    int argc, ret_val = -1;
  238. X    u_long save_do_pipe = ison(glob_flags, DO_PIPE);
  239. X    u_long save_is_pipe = ison(glob_flags, IS_PIPE);
  240. X    char dummy_list[MAXMSGS_BITS];
  241. X
  242. X    turnoff(glob_flags, DO_PIPE);
  243. X    turnoff(glob_flags, IS_PIPE);
  244. X    if (argv = make_command(buf, TRPL_NULL, &argc))
  245. X    ret_val = do_command(argc, argv, list? list : dummy_list);
  246. X    if (save_do_pipe)
  247. X    turnon(glob_flags, DO_PIPE);
  248. X    else
  249. X    turnoff(glob_flags, DO_PIPE);
  250. X    if (save_is_pipe)
  251. X    turnon(glob_flags, IS_PIPE);
  252. X    else
  253. X    turnoff(glob_flags, IS_PIPE);
  254. X    return ret_val;
  255. X}
  256. X
  257. Xglob_test(s)
  258. Xchar *s;
  259. X{
  260. X    print("%s: glob_flags =", s);
  261. X    if (ison(glob_flags, DO_UPDATE))
  262. X    print_more(" DO_UPDATE");
  263. X    if (ison(glob_flags, REV_VIDEO))
  264. X    print_more(" REV_VIDEO");
  265. X    if (ison(glob_flags, CONT_PRNT))
  266. X    print_more(" CONT_PRNT");
  267. X    if (ison(glob_flags, DO_SHELL))
  268. X    print_more(" DO_SHELL");
  269. X    if (ison(glob_flags, DO_PIPE))
  270. X    print_more(" DO_PIPE");
  271. X    if (ison(glob_flags, IS_PIPE))
  272. X    print_more(" IS_PIPE");
  273. X    if (ison(glob_flags, IGN_SIGS))
  274. X    print_more(" IGN_SIGS");
  275. X    if (ison(glob_flags, IGN_BANG))
  276. X    print_more(" IGN_BANG");
  277. X    if (ison(glob_flags, ECHO_FLAG))
  278. X    print_more(" ECHO_FLAG");
  279. X    if (ison(glob_flags, IS_GETTING))
  280. X    print_more(" IS_GETTING");
  281. X    if (ison(glob_flags, PRE_CURSES))
  282. X    print_more(" PRE_CURSES");
  283. X    if (ison(glob_flags, READ_ONLY))
  284. X    print_more(" READ_ONLY");
  285. X    if (ison(glob_flags, REDIRECT))
  286. X    print_more(" REDIRECT");
  287. X    if (ison(glob_flags, WAS_INTR))
  288. X    print_more(" WAS_INTR");
  289. X    if (ison(glob_flags, WARNING))
  290. X    print_more(" WARNING");
  291. X    if (ison(glob_flags, NEW_MAIL))
  292. X    print_more(" NEW_MAIL");
  293. X    if (ison(glob_flags, CNTD_CMD))
  294. X    print_more(" CNTD_CMD");
  295. X    if (ison(glob_flags, IS_SENDING))
  296. X    print_more(" IS_SENDING");
  297. X    if (ison(glob_flags, MIL_TIME))
  298. X    print_more(" MIL_TIME");
  299. X    if (ison(glob_flags, DATE_RECV))
  300. X    print_more(" DATE_RECV");
  301. X    if (ison(glob_flags, IN_MACRO))
  302. X    print_more(" IN_MACRO");
  303. X    if (ison(glob_flags, LINE_MACRO))
  304. X    print_more(" LINE_MACRO");
  305. X    if (ison(glob_flags, QUOTE_MACRO))
  306. X    print_more(" QUOTE_MACRO");
  307. X    print_more("\n");
  308. X}
  309. X
  310. X/*
  311. X * change the status flags for messages.
  312. X *    flags * P        preserves all messages.
  313. X *    flags 4-7 -S    remove the "saved" status on msgs 4-7
  314. X *    flags +r        add the replied-to bit on the current message.
  315. X */
  316. Xmsg_flags(c, v, list)
  317. Xregister char **v, *list;
  318. X{
  319. X    register int    i, modify = 0;
  320. X    register u_long    newflag = 0;
  321. X    char sent[32], recv[32];
  322. X
  323. X    if (c && *++v && !strcmp(*v, "-?"))
  324. X    return help(0, "msg_flags", cmd_help);
  325. X    if (c && (c = get_msg_list(v, list)) == -1)
  326. X    return -1;
  327. X    if (v && *(v += (c-1))) {
  328. X    turnon(glob_flags, DO_UPDATE);
  329. X    while (*++v)
  330. X        for (c = 0; v[0][c]; c++)
  331. X        switch (lower(v[0][c])) {
  332. X            case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD);
  333. X            when 'd' : turnon(newflag, DELETE);
  334. X            when 'p' : turnon(newflag, PRESERVE);
  335. X            when 's' : turnon(newflag, SAVED);
  336. X            when 'u' : turnon(newflag, UNREAD); /* fall thru! */
  337. X            case 'o' : turnon(newflag, OLD);
  338. X            when 'r' :
  339. X            if (v[0][c] == 'R')
  340. X                turnoff(newflag, UNREAD), turnon(newflag, OLD);
  341. X            else
  342. X                turnon(newflag, REPLIED);
  343. X            when '+' : modify = 1;
  344. X            when '-' : modify = 2;
  345. X            otherwise: return help(0, "msg_flags", cmd_help);
  346. X        }
  347. X    }
  348. X
  349. X    for (i = 0; i < msg_cnt; i++) {
  350. X    if (!msg_bit(list, i))
  351. X        continue;
  352. X    else if (!newflag) {
  353. X        wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1,
  354. X        msg[i].m_offset, msg[i].m_lines, msg[i].m_size);
  355. X        if (ison(msg[i].m_flags, UNREAD))
  356. X        wprint(" UNREAD");
  357. X        if (ison(msg[i].m_flags, OLD))
  358. X        wprint(" OLD");
  359. X        if (ison(msg[i].m_flags, DELETE))
  360. X        wprint(" DELETE");
  361. X        if (ison(msg[i].m_flags, PRESERVE))
  362. X        wprint(" PRESERVE");
  363. X        if (ison(msg[i].m_flags, REPLIED))
  364. X        wprint(" REPLIED");
  365. X        if (ison(msg[i].m_flags, SAVED))
  366. X        wprint(" SAVED");
  367. X        if (ison(msg[i].m_flags, UPDATE_STATUS))
  368. X        wprint(" UPDATE_STATUS");
  369. X        strcpy(sent, date_to_ctime(msg[i].m_date_sent));
  370. X        strcpy(recv, date_to_ctime(msg[i].m_date_recv));
  371. X        wprint("\n\tsent: %s\trecv: %s", sent, recv);
  372. X    } else switch (modify) {
  373. X        case 0: msg[i].m_flags = newflag;
  374. X        when 1: msg[i].m_flags |= newflag;
  375. X        when 2: msg[i].m_flags &= ~newflag;
  376. X    }
  377. X    }
  378. X    return 0;
  379. X}
  380. X
  381. X/*
  382. X * Internal pager.  Start the internal pager by passing the name of
  383. X * the pager in buf and passing TRUE as start_pager. If the internal
  384. X * pager is desired, pass NULL as buf.  Continue paging by passing
  385. X * FALSE as start_pager and the buf is the stuff to pass thru to the
  386. X * pager.  End paging by passing NULL as buf and FALSE as start_pager.
  387. X * If the pager can't be used, or is null, we're paging ourselves.
  388. X * Windows does nothing but echo buf to the msg window (this will change).
  389. X * The "buf" passed to the pager should be a line at a time so as to
  390. X * count \n's.  If there is more than one newline, the first one is nulled
  391. X * and the next line done by calling do_pager recursively.  WARNING: because
  392. X * "buf" is changed, it is *illegal* for anyone calling this routine to pass
  393. X * _constant_ strings --they should be strcpy'ed or sprintf'ed into a temp
  394. X * buff before passing to this routine!  Otherwise, ANSI-C compilers will
  395. X * core dump.  This is because constant strings are read-only.
  396. X * Return EOF if pager died, user exited pager, or if user types 'q'
  397. X * at the --more-- prompt for the internal pager.
  398. X */
  399. Xdo_pager(buf, start_pager)
  400. Xregister char *buf;
  401. X{
  402. X    static FILE *pp;
  403. X    static int cnt, len;
  404. X    static u_long save_echo_flag;
  405. X
  406. X#ifdef SUNTOOL
  407. X    if (istool) {
  408. X    if (buf && !start_pager)
  409. X        Addstr(buf);
  410. X    return 0;
  411. X    }
  412. X#endif /* SUNTOOL */
  413. X    if (start_pager) {
  414. X    turnon(glob_flags, IGN_SIGS);
  415. X    if (!buf) {
  416. X        /* internal pager */
  417. X        save_echo_flag = ison(glob_flags, ECHO_FLAG);
  418. X        pp = stdout;
  419. X        if (save_echo_flag) {
  420. X        turnoff(glob_flags, ECHO_FLAG);
  421. X        echo_off();
  422. X        }
  423. X    } else {
  424. X        echo_on();
  425. X        if (!(pp = popen(buf, "w")))
  426. X        error(buf);
  427. X    }
  428. X    cnt = len = 0;
  429. X    } else if (!buf) {
  430. X    if (pp && pp != stdout)
  431. X        pclose(pp);
  432. X    pp = NULL_FILE;
  433. X    if (save_echo_flag) {
  434. X        echo_on();
  435. X        turnon(glob_flags, ECHO_FLAG);
  436. X    } else
  437. X        echo_off();
  438. X    turnoff(glob_flags, IGN_SIGS);
  439. X    } else if (pp != stdout)
  440. X    return fputs(buf, pp); /* returns EOF if user exited pager */
  441. X    else {
  442. X    register char c = 0, *cr = index(buf, '\n');
  443. X    len += strlen(buf);
  444. X    if (cr) {
  445. X        int maxlen =
  446. X#ifdef CURSES
  447. X        iscurses ? COLS :
  448. X#endif /* CURSES */
  449. X        80;
  450. X        if (len > maxlen)
  451. X        cnt += len / maxlen;
  452. X        len = 0;
  453. X    }
  454. X    if (cr && (c = *++cr) != '\0')
  455. X        *cr = 0; /* send one line to stdout and prompt for more */
  456. X    (void) fputs(buf, pp);
  457. X    if (cr && (++cnt / (crt-1))) {
  458. X        int n = c_more(NULL);
  459. X        if (n == '\n' || n == '\r')
  460. X        cnt--; /* go line by line */
  461. X        else if (n == CTRL(D) || lower(n) == 'd' || n < 0) {
  462. X        clearerr(stdin);
  463. X        cnt = ((crt-1)/2);
  464. X        } else if (lower(n) == 'q')
  465. X        /* could check if "c" is set, but... see warning above */
  466. X        return EOF;
  467. X        else
  468. X        cnt = 1;
  469. X    }
  470. X    if (c) {
  471. X        *cr = c;
  472. X        return do_pager(cr, FALSE);
  473. X    }
  474. X    }
  475. X    return 0;
  476. X}
  477. X
  478. X/* curses based "more" like option */
  479. Xc_more(p)
  480. Xregister char *p;
  481. X{
  482. X    register int c;
  483. X
  484. X    if (!p)
  485. X    p = "--more--";
  486. X    print_more(p);
  487. X    
  488. X    while ((c = getchar()) >= 0 && c != CTRL(D) && !isspace(c) &&
  489. X       c != '\n' && c != '\r' && lower(c) != 'q' && lower(c) != 'd')
  490. X    bell();
  491. X    if (ison(glob_flags, ECHO_FLAG) && c != '\n' && c != '\r')
  492. X    while (getchar() != '\n');
  493. X    printf("\r%*c\r", strlen(p), ' '), fflush(stdout); /* remove the prompt */
  494. X    return c;
  495. X}
  496. X
  497. X/*
  498. X * Your "signature" is of the type:
  499. X *    file_or_path
  500. X *    $variable
  501. X *    \ literal string preceded by a backslash.
  502. X * The variable will be expanded into its string value.
  503. X * To sign the letter, the list of addresses is passed to this routine
  504. X * (separated by whitespace and/or commas).  No comment fields!
  505. X *
  506. X * If "autosign2" is set, then it must be of the form:
  507. X *    autosign2 = "*user user !host !some!path @dom.ain: ~/.sign2"
  508. X *
  509. X * The colon terminates the user/host lists from the "signature" to the right.
  510. X *
  511. X * Whitespace or commas separate tokens.  If everyone on the list exists in
  512. X * the autosign2 list, the alternate signature is used. In case of syntax
  513. X * error, the alternate signature is used without checks (e.g. if the colon
  514. X * is missing).  The alternate signature == null is the same as not signing
  515. X * the letter. An empty list forces signature2.
  516. X *
  517. X * If autosign2 is not set at all, then autosign is checked and used.
  518. X * autosign = <signature>
  519. X */
  520. Xsign_letter(list, flags, fp)
  521. Xregister char *list; /* list of addresses -- no comment fields */
  522. Xu_long flags;
  523. XFILE *fp;
  524. X{
  525. X    char buf[BUFSIZ], *signature;
  526. X    register char *p = NULL, *p2;
  527. X    FILE     *pp2;
  528. X    int     lines = 0;
  529. X
  530. X    while (isspace(*list))
  531. X    list++;
  532. X    if (ison(flags, SIGN)) {
  533. X    if (!(p = do_set(set_options, "autosign2")))
  534. X        buf[0] = 0;
  535. X    else {
  536. X        if (!(signature = index(p, ':')))
  537. X        (void) strcpy(buf, p); /* No colon; use entire string as sig */
  538. X        else {
  539. X        int ret_val = 0;
  540. X        *signature = 0;
  541. X        /* p now points to a list of addresses and p2 points to the
  542. X         * signature format to use. Check that each address in the list
  543. X         * provided (parameter) matches the "addrs" in autosign2.
  544. X         */
  545. X        skipspaces(0);
  546. X        if (!*p)
  547. X            /* autosign2 = " : <signature>"  send to all recipients */
  548. X            ret_val = 1;
  549. X        else if (p = alias_to_address(p)) {
  550. X            rm_cmts_in_addr(p);
  551. X            ret_val = compare_addrs(list, p, NULL);
  552. X        }
  553. X        *signature++ = ':'; /* must reset first! */
  554. X        buf[0] = 0;
  555. X        if (ret_val) {
  556. X            while (isspace(*signature))
  557. X            signature++;
  558. X            /* Null signatures don't sign anything. */
  559. X            if (!*strcpy(buf, signature))
  560. X            return;
  561. X        }
  562. X        }
  563. X    }
  564. X    if (!buf[0]) {
  565. X        if (!(p = do_set(set_options, "autosign")) || !*p) {
  566. X        char *home;
  567. X        if (!(home = do_set(set_options, "home")) || !*home)
  568. X            home = ALTERNATE_HOME;
  569. X        (void) sprintf(buf, "%s/%s", home, SIGNATURE);
  570. X        } else
  571. X        (void) strcpy(buf, p);
  572. X        wprint("Signing letter... ");
  573. X    } else
  574. X        wprint("Using alternate signature... ");
  575. X    /* precede _file_ signatures ONLY with "\n-- \n" */
  576. X    if (buf[0] != '\\' && buf[0] != '$')
  577. X        fputs("\n-- \n", fp);
  578. X    else
  579. X        fputc('\n', fp);
  580. X    fflush(fp);
  581. X    (void) fseek(fp, 0L, 2); /* guarantee position at end of file */
  582. X    if (*buf == '$')
  583. X        if (!(p = do_set(set_options, buf)))
  584. X        wprint("(%s isn't set -- letter not signed)\n", buf);
  585. X        else {
  586. X        putstring(p+1, fp);
  587. X        wprint("\n");
  588. X        }
  589. X    else if (*buf == '\\') {
  590. X        putstring(buf, fp);
  591. X        wprint("\n");
  592. X    } else
  593. X        file_to_fp(buf, fp, "r");
  594. X    }
  595. X
  596. X    fflush(stdout); /* for sys-v and older xenix */
  597. X
  598. X    /* if fortune is set, check to see if fortunates is set. If so,
  599. X     * check to see if all the recipient are on the fortunates list.
  600. X     */
  601. X    if (ison(flags, DO_FORTUNE)) {
  602. X    if (p = do_set(set_options, "fortunates")) {
  603. X        int ret_val;
  604. X        if (!(p = alias_to_address(p)))
  605. X        return; /* no reason to hang around */
  606. X        rm_cmts_in_addr(p);
  607. X        if (!compare_addrs(list, p, buf)) {
  608. X        wprint("\"fortunates\" does not contain \"%s\".\n", buf);
  609. X        wprint("No fortune added.\n");
  610. X        return;
  611. X        }
  612. X    }
  613. X    wprint("You may be fortunate... ");
  614. X    if ((p = do_set(set_options, "fortune")) && *p == '/')
  615. X        (void) strcpy(buf, p);
  616. X    else
  617. X        (void) sprintf(buf, "%s %s", FORTUNE, (p && *p == '-')? p: "-s");
  618. X    if (!(pp2 = popen(buf, "r")))
  619. X        error(buf);
  620. X    else {
  621. X        turnon(glob_flags, IGN_SIGS);
  622. X        (void) fseek(fp, 0L, 2); /* go to end of file */
  623. X        while (fgets(buf, sizeof(buf), pp2))
  624. X        fputs(buf, fp), lines++;
  625. X        (void) pclose(pp2);
  626. X        turnoff(glob_flags, IGN_SIGS);
  627. X        fflush(fp);
  628. X        wprint("added %d line%s\n", lines, lines == 1? "" : "s");
  629. X    }
  630. X    }
  631. X    fflush(stdout); /* for sys-v and older xenix */
  632. X}
  633. X
  634. X
  635. X/* return -1 since function doesn't affect messages */
  636. Xcheck_flags(flags)
  637. Xu_long flags;
  638. X{
  639. X    print_more(" ");
  640. X    if (ison(flags, VERBOSE))
  641. X    print_more("VERBOSE ");
  642. X    if (ison(flags, INCLUDE))
  643. X    print_more("INCLUDE ");
  644. X    if (ison(flags, INCLUDE_H))
  645. X    print_more("INCLUDE_H ");
  646. X    if (ison(flags, EDIT))
  647. X    print_more("EDIT ");
  648. X    if (ison(flags, SIGN))
  649. X    print_more("SIGN ");
  650. X    if (ison(flags, DO_FORTUNE))
  651. X    print_more("DO_FORTUNE ");
  652. X    if (ison(flags, NO_HEADER))
  653. X    print_more("NO_HEADER ");
  654. X    if (ison(flags, DELETE))
  655. X    print_more("DELETE ");
  656. X    if (ison(flags, OLD))
  657. X    print_more("OLD ");
  658. X    if (ison(flags, UNREAD))
  659. X    print_more("UNREAD ");
  660. X    if (ison(flags, UPDATE_STATUS))
  661. X    print_more("UPDATE_STATUS ");
  662. X    if (ison(flags, NO_PAGE))
  663. X    print_more("NO_PAGE ");
  664. X    if (ison(flags, INDENT))
  665. X    print_more("INDENT ");
  666. X    if (ison(flags, NO_IGNORE))
  667. X    print_more("NO_IGNORE ");
  668. X    if (ison(flags, PRESERVE))
  669. X    print_more("PRESERVE ");
  670. X    print_more("\n");
  671. X    return -1;
  672. X}
  673. END_OF_FILE
  674. if test 18158 -ne `wc -c <'misc.c'`; then
  675.     echo shar: \"'misc.c'\" unpacked with wrong size!
  676. fi
  677. # end of 'misc.c'
  678. fi
  679. if test -f 'setopts.c' -a "${1}" != "-c" ; then 
  680.   echo shar: Will not clobber existing file \"'setopts.c'\"
  681. else
  682. echo shar: Extracting \"'setopts.c'\" \(18443 characters\)
  683. sed "s/^X//" >'setopts.c' <<'END_OF_FILE'
  684. X/* setopts.c    (c) copyright 1986 (Dan Heller) */
  685. X
  686. X#include "mush.h"
  687. X#include "bindings.h"
  688. X
  689. X/* add an option indicated by "set option[=value]" or by "alias name alias"
  690. X * function is recursive, so multilists get appended accordingly
  691. X */
  692. Xadd_option(list, argv)
  693. Xregister struct options **list;
  694. Xregister char **argv;
  695. X{
  696. X    register struct options *tmp;
  697. X    struct options *calloc();
  698. X    register char *option, *value = NULL;
  699. X
  700. X    if (!(option = *argv))
  701. X    return 1;
  702. X    /* check for one of three forms:
  703. X     * option=value    option = value  option= value
  704. X     * value can be in quotes to preserve whitespace
  705. X     */
  706. X    if (*++argv && !strcmp(*argv, "=")) {
  707. X    if (value = *++argv) /* example: "set foo = " */
  708. X        ++argv;
  709. X    } else if (value = index(option, '=')) {
  710. X    /* option=value  strip into option="option" value="value"; (quotes?) */
  711. X    register char c, *p2;
  712. X    *value = 0; /* option is now a null terminated `option' */
  713. X    if ((c = *++value) == '"' || c == '\'') {
  714. X        *value++ = 0;
  715. X        if (!(p2 = index(value, c))) {
  716. X        print("No matching %c for %s.\n", c, option);
  717. X        return 0;
  718. X        } else
  719. X        *p2 = 0;
  720. X    } else if (!c) {  /* example: "set crt=" */
  721. X        if (!*argv) {
  722. X        print("No value for %s.\n", option);
  723. X        return 0;
  724. X        }
  725. X        value = *argv++;
  726. X    }
  727. X    }
  728. X
  729. X    /* check for internal vars that can't be set this way */
  730. X    if (check_internal(option)) {
  731. X    print("You can't change %s with \"set\".\n", option);
  732. X    return 0;
  733. X    }
  734. X
  735. X    /* check to see if option is already set by attempting to unset it */
  736. X    (void) un_set(list, option);
  737. X
  738. X    /* now make a new option struct and set fields */
  739. X    if (!(tmp = calloc((unsigned)1, sizeof(struct options)))) {
  740. X    error("calloc");
  741. X    return -1;
  742. X    }
  743. X    tmp->option = savestr(option);
  744. X    tmp->value = savestr(value); /* strdup handles the NULL case */
  745. X
  746. X    tmp->next = *list;
  747. X    *list = tmp;
  748. X
  749. X    /* check for options which must have values or are used frequently */
  750. X    if (*list == set_options) {
  751. X#if defined(CURSES) || defined(SUNTOOL)
  752. X    if (!strcmp(tmp->option, "no_reverse"))
  753. X        turnoff(glob_flags, REV_VIDEO);
  754. X    else
  755. X#endif /* CURSES || SUNTOOL */
  756. X    if (!strcmp(tmp->option, "prompt"))
  757. X        prompt = (tmp->value)? tmp->value : DEF_PROMPT;
  758. X    else if (!strcmp(tmp->option, "warning"))
  759. X        turnon(glob_flags, WARNING);
  760. X    else if (!strcmp(tmp->option, "mil_time"))
  761. X        turnon(glob_flags, MIL_TIME);
  762. X#ifndef MSG_SEPARATOR
  763. X    else if (!strcmp(tmp->option, "date_received"))
  764. X        turnon(glob_flags, DATE_RECV);
  765. X#endif /* MSG_SEPARATOR */
  766. X    else if (!strcmp(tmp->option, "escape"))
  767. X        escape = (tmp->value)? tmp->value : DEF_ESCAPE;
  768. X    else if (!strcmp(tmp->option, "hdr_format"))
  769. X        hdr_format = (tmp->value)? tmp->value : DEF_HDR_FMT;
  770. X    else if (!strcmp(tmp->option, "crt")) {
  771. X        if (!istool)
  772. X        crt = (tmp->value)? max(atoi(tmp->value), 2): 18;
  773. X    } else if (!strcmp(tmp->option, "screen")) {
  774. X        screen = (tmp->value)? max(atoi(tmp->value), 1): 18;
  775. X#ifdef CURSES
  776. X        if (iscurses && screen > LINES-2)
  777. X        screen = LINES-2;
  778. X#endif /* CURSES */
  779. X    } else if (!strcmp(tmp->option, "wrapcolumn")) {
  780. X        char wval[16];
  781. X        wrapcolumn =
  782. X        (tmp->value && *(tmp->value))? max(atoi(tmp->value), 0): 78;
  783. X#ifdef CURSES
  784. X        /* Use COLS-2 because of silly terminals like vt100 */
  785. X        if (iscurses && wrapcolumn > COLS - 2)
  786. X        wrapcolumn = COLS - 2;
  787. X#endif /* CURSES */
  788. X        xfree(tmp->value);
  789. X        tmp->value = savestr(sprintf(wval, "%d", wrapcolumn));
  790. X    } else if (!strcmp(tmp->option, "history"))
  791. X        init_history((value && *value)? atoi(value) : 1);
  792. X    else if (!strcmp(tmp->option, "known_hosts")) {
  793. X        register char *p;
  794. X        int n;
  795. X        /* in case user separated with commas */
  796. X        for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  797. X        *p = ' ';
  798. X        free_vec(known_hosts);
  799. X        known_hosts = mk_argv(tmp->value, &n, FALSE);
  800. X    } else if (!strcmp(tmp->option, "hostname")) {
  801. X        register char *p;
  802. X        int n;
  803. X        /* in case user separated with commas */
  804. X        for (p = index(tmp->value, ','); p; p = index(p+1, ','))
  805. X        *p = ' ';
  806. X        free_vec(ourname);
  807. X        ourname = mk_argv(tmp->value, &n, FALSE);
  808. X    }
  809. X    }
  810. X
  811. X    if (*argv)
  812. X    return add_option(list, argv);
  813. X    return 1;
  814. X}
  815. X
  816. X/*
  817. X * If str is NULL, just print options and their values. Note that numerical
  818. X * values are not converted to int upon return.  If str is not NULL
  819. X * return the string that matched, else return NULL;
  820. X */
  821. Xchar *
  822. Xdo_set(list, str)
  823. Xregister struct options *list;
  824. Xregister char *str;
  825. X{
  826. X    register struct options *opts;
  827. X#ifdef SUNTOOL
  828. X    int x,y;
  829. X
  830. X    if (istool && !str)
  831. X    y = 10 + 2 * l_height(LARGE);
  832. X#endif /* SUNTOOL */
  833. X
  834. X    if (!str && !istool)
  835. X    (void) do_pager(NULL, TRUE); /* page using internal pager */
  836. X
  837. X    for (opts = list; opts; opts = opts->next)
  838. X    if (!str) {
  839. X#ifdef SUNTOOL
  840. X        if (istool)
  841. X        pw_text(msg_win, 5, y, PIX_SRC, fonts[DEFAULT], opts->option);
  842. X        else
  843. X#endif /* SUNTOOL */
  844. X        (void) do_pager(opts->option, FALSE);
  845. X        if (opts->value)
  846. X#ifdef SUNTOOL
  847. X        if (istool) {
  848. X            x = 30*l_width(DEFAULT);
  849. X            pw_text(msg_win, x,y, PIX_SRC, fonts[DEFAULT], opts->value);
  850. X            pw_text(msg_win, x+1, y, PIX_SRC|PIX_DST,
  851. X                 fonts[DEFAULT], opts->value);
  852. X            x += strlen(opts->value)*l_width(DEFAULT);
  853. X        } else
  854. X#endif /* SUNTOOL */
  855. X        {
  856. X            (void) do_pager("     \t", FALSE);
  857. X            (void) do_pager(opts->value, FALSE);
  858. X        }
  859. X#ifdef SUNTOOL
  860. X        if (istool)
  861. X        Clrtoeol(msg_win, x, y, DEFAULT), y += l_height(DEFAULT);
  862. X        else
  863. X#endif /* SUNTOOL */
  864. X        if (do_pager("\n", FALSE) == EOF)
  865. X            break;
  866. X    } else {
  867. X        if (strcmp(str, opts->option))
  868. X        continue;
  869. X        if (opts->value)
  870. X        return opts->value;
  871. X        else
  872. X        return "";
  873. X    }
  874. X
  875. X    if (!str && !istool)
  876. X    (void) do_pager(NULL, FALSE); /* terminate internal pager */
  877. X
  878. X    /* if we still haven't matched, check for environment vars */
  879. X    if (str && list == set_options) {
  880. X    register int N, n;
  881. X    for (N = 0; environ[N]; N++) {
  882. X        char *p = index(environ[N], '=');
  883. X        if (p)
  884. X        *p = 0;
  885. X        n = lcase_strncmp(str, environ[N], -1);
  886. X        if (p)
  887. X        *p = '=';
  888. X        if (!n)
  889. X        return p+1;
  890. X    }
  891. X    }
  892. X    return NULL;
  893. X}
  894. X
  895. X/*
  896. X * unset the variable described by p in the list "list".
  897. X * if the variable isn't set, then return 0, else return 1.
  898. X */
  899. Xun_set(list, p)
  900. Xregister struct options **list;
  901. Xregister char *p;
  902. X{
  903. X    register struct options *opts = *list, *tmp;
  904. X
  905. X    if (!list || !*list || !p || !*p)
  906. X    return 0;
  907. X    if (*list == set_options) {
  908. X#if defined(CURSES) || defined(SUNTOOL)
  909. X    if (!strcmp(p, "no_reverse"))
  910. X        turnon(glob_flags, REV_VIDEO);
  911. X    else
  912. X#endif /* CURSES || SUNTOOL */
  913. X    if (!strcmp(p, "prompt"))
  914. X        prompt = DEF_PROMPT;
  915. X    else if (!strcmp(p, "warning"))
  916. X        turnoff(glob_flags, WARNING);
  917. X    else if (!strcmp(p, "mil_time"))
  918. X        turnoff(glob_flags, MIL_TIME);
  919. X#ifndef MSG_SEPARATOR
  920. X    else if (!strcmp(p, "date_received"))
  921. X        turnoff(glob_flags, DATE_RECV);
  922. X#endif /* MSG_SEPARATOR */
  923. X    else if (!strcmp(p, "escape"))
  924. X        escape = DEF_ESCAPE;
  925. X    else if (!strcmp(p, "hdr_format"))
  926. X        hdr_format = DEF_HDR_FMT;
  927. X    else if (!strcmp(p, "crt"))
  928. X        crt = 18;
  929. X    else if (!strcmp(p, "screen")) {
  930. X        screen = 18;
  931. X#ifdef CURSES
  932. X        if (iscurses && screen > LINES-2)
  933. X        screen = LINES-2;
  934. X#endif /* CURSES */
  935. X    } else if (!strcmp(p, "wrapcolumn"))
  936. X        wrapcolumn = 0;
  937. X    else if (!strcmp(p, "history"))
  938. X        init_history(1);
  939. X    else if (!strcmp(p, "known_hosts")) {
  940. X        free_vec(known_hosts);
  941. X        known_hosts = DUBL_NULL;
  942. X    } else if (!strcmp(p, "hostname")) {
  943. X        free_vec(ourname);
  944. X        ourname = DUBL_NULL;
  945. X    }
  946. X    }
  947. X
  948. X    if (!strcmp(p, opts->option)) {
  949. X    *list = (*list)->next;
  950. X    xfree (opts->option);
  951. X    if (opts->value)
  952. X        xfree(opts->value);
  953. X    xfree((char *)opts);
  954. X    return 1;
  955. X    }
  956. X    for ( ; opts->next; opts = opts->next)
  957. X    if (!strcmp(p, opts->next->option)) {
  958. X        tmp = opts->next;
  959. X        opts->next = opts->next->next;
  960. X        xfree (tmp->option);
  961. X        if (tmp->value)
  962. X        xfree(tmp->value);
  963. X        xfree ((char *)tmp);
  964. X        return 1;
  965. X    }
  966. X    return 0;
  967. X}
  968. X
  969. X/* The functions below return 0 since they don't affect
  970. X * messages.
  971. X */
  972. Xset(n, argv, list)
  973. Xregister int n;
  974. Xregister char **argv;
  975. Xchar *list;
  976. X{
  977. X    char firstchar = **argv;
  978. X    register char *cmd = *argv;
  979. X    register struct options **optlist;
  980. X    char buf[BUFSIZ];
  981. X
  982. X    if (*cmd == 'u')
  983. X    cmd += 2;
  984. X    if (*++argv && !strcmp(*argv, "-?"))
  985. X    return help(0, (*cmd == 'i')? "ignore": "set", cmd_help);
  986. X
  987. X    if (*argv && **argv == '?') {
  988. X    int incurses;
  989. X    if (!strcmp(*argv, "?all")) {
  990. X        if (incurses = iscurses) /* assign and compare to TRUE */
  991. X        clr_bot_line(), iscurses = FALSE;
  992. X        (void) do_pager(NULL, TRUE); /* start internal pager */
  993. X        for (n = 0; variable_stuff(n, NULL, buf); n++)
  994. X        if (do_pager(strcat(buf, "\n"), FALSE) == EOF)
  995. X            break;
  996. X        (void) do_pager(NULL, FALSE); /* terminate pager */
  997. X        iscurses = incurses;
  998. X    } else {
  999. X        /* May return null if variable not set. */
  1000. X        (void) variable_stuff(0, (*argv)+1, buf);
  1001. X        print("%s\n", buf);
  1002. X    }
  1003. X    return 0;
  1004. X    }
  1005. X
  1006. X    if (firstchar == 'u') {
  1007. X    if (!*argv) {
  1008. X        print("%s what?\n", cmd);
  1009. X        return -1;
  1010. X    } else {
  1011. X        optlist = (*cmd == 'i')? &ignore_hdr : &set_options;
  1012. X        do  if (!strcmp(*argv, "*"))
  1013. X            while (*optlist)
  1014. X            (void) un_set(optlist, (*optlist)->option);
  1015. X        else if (!un_set(optlist, *argv))
  1016. X            print("un%s: %s not set\n",
  1017. X            (*cmd == 'i')? "ignore" : "set", *argv);
  1018. X        while (*++argv);
  1019. X    }
  1020. X    return 0;
  1021. X    }
  1022. X
  1023. X    if (!*argv) {
  1024. X    (void) do_set((*cmd == 'i')? ignore_hdr: set_options, NULL);
  1025. X    return 0;
  1026. X    }
  1027. X
  1028. X    /*
  1029. X     * Check for input redirection.  If so, set the variable to the ascii
  1030. X     * value of the current msg_list.
  1031. X     */
  1032. X    if (ison(glob_flags, IS_PIPE)) {
  1033. X    char *newargv[4];
  1034. X
  1035. X    if (*cmd == 'i') {
  1036. X        print("You can't pipe to the \"%s\" command.\n", cmd);
  1037. X        return -1;
  1038. X    }
  1039. X    list_to_str(list, buf);
  1040. X    if (!buf[0])
  1041. X        return -1;
  1042. X    newargv[0] = argv[0];
  1043. X    newargv[1] = "=";
  1044. X    newargv[2] = buf;
  1045. X    newargv[3] = NULL;
  1046. X    (void) add_option(&set_options, newargv);
  1047. X    return 0;
  1048. X    }
  1049. X
  1050. X    /*
  1051. X     * finally, just set the variable the user requested.
  1052. X     */
  1053. X    (void) add_option((*cmd == 'i')? &ignore_hdr: &set_options, argv);
  1054. X    return 0;
  1055. X}
  1056. X
  1057. X/*
  1058. X *   The alts list is a list of hostnames or pathnames where the user
  1059. X * has an account.  If he doesn't specify "metoo", then when replying
  1060. X * to mail, if his address is listed, it will be removed.  The syntax
  1061. X * is compatible with ucb Mail in that just hostnames can be used.
  1062. X * However, there is an added feature that mush provides which another
  1063. X * login name or path to another login can be specified by preceding the
  1064. X * path or login with a !
  1065. X * "argv" may be a file pointer to write the data into by use of save_opts()
  1066. X */
  1067. Xalts(argc, argv)
  1068. Xregister char **argv;
  1069. X{
  1070. X    char buf[BUFSIZ], *p;
  1071. X
  1072. X    /* check here first because a 0 argc means to write it to a file */
  1073. X    if (argc <= 1) {
  1074. X    int n;
  1075. X    if (!alternates)
  1076. X        return;
  1077. X    if (argc == 0)
  1078. X        fprintf((FILE *)argv, "alts ");
  1079. X    for (n = 0; alternates[n]; n++) {
  1080. X        p = 0;
  1081. X        (void) reverse(strcpy(buf, alternates[n]));
  1082. X        if (isalpha(buf[0]) && (p = rindex(buf, '!')))
  1083. X        *p = 0;
  1084. X        if (argc == 0)
  1085. X        fprintf((FILE *)argv, "%s ", buf);
  1086. X        else
  1087. X        wprint("%s ", buf);
  1088. X        if (p)
  1089. X        *p = '!';
  1090. X    }
  1091. X    if (argc == 0)
  1092. X        fputc('\n', (FILE *)argv);
  1093. X    else
  1094. X        wprint("\n");
  1095. X    return 0;
  1096. X    }
  1097. X
  1098. X    if (argc-- && *++argv && !strcmp(*argv, "-?"))
  1099. X    return help(0, "alts", cmd_help);
  1100. X
  1101. X    free_vec(alternates);
  1102. X    if (alternates = (char **)calloc((unsigned)argc+1, sizeof(char *)))
  1103. X    while (argc-- > 0) {
  1104. X        if (argv[argc][0] != '!' && argv[argc][0] != '*') {
  1105. X        p = buf + Strcpy(buf, argv[argc]);
  1106. X        *p++ = '!', p += Strcpy(p, login);
  1107. X        alternates[argc] = savestr(reverse(buf));
  1108. X        } else
  1109. X        alternates[argc] = savestr(reverse(argv[argc]));
  1110. X    }
  1111. X    return 0;
  1112. X}
  1113. X
  1114. Xsave_opts(cnt, argv)
  1115. Xchar **argv;
  1116. X{
  1117. X    char file[256], *tmp;
  1118. X    register FILE *fp;
  1119. X
  1120. X    if (cnt && *++argv && !strcmp(*argv, "-?"))
  1121. X    return help(0, "source_help", cmd_help);
  1122. X    if (cnt && *argv)
  1123. X    (void) strcpy(file, *argv);
  1124. X    else if (tmp = getenv("MAILRC"))
  1125. X    (void) strcpy(file, tmp);
  1126. X    else {
  1127. X    char *home = do_set(set_options, "home");
  1128. X    if (!home || !*home)
  1129. X        home = ALTERNATE_HOME;
  1130. X    /* if .mushrc doesn't exist, check .mailrc. If neither, force .mushrc */
  1131. X    if (Access(sprintf(file, "%s/%s", home, MAILRC), F_OK) &&
  1132. X            Access(sprintf(file, "%s/%s", home, ALTERNATE_RC), F_OK))
  1133. X        (void) sprintf(file, "%s/%s", home, MAILRC);
  1134. X    }
  1135. X
  1136. X    cnt = 1;
  1137. X    tmp = getpath(file, &cnt);
  1138. X    if (cnt) {
  1139. X    if (cnt == -1)
  1140. X        print("%s: %s\n", file, tmp);
  1141. X    else
  1142. X        print("%s is a directory.\n", tmp);
  1143. X    return -1;
  1144. X    }
  1145. X    /* See if the file exists and confirm overwrite */
  1146. X    if (!Access(tmp, F_OK)) {
  1147. X    int overwrite = TRUE;
  1148. X    char buf[4];
  1149. X    print("\"%s\" exists. Overwrite? ", tmp);
  1150. X    if (!istool) {
  1151. X        if (Getstr(buf, 3, 0) <= 0 || lower(*buf) != 'y')
  1152. X        overwrite = FALSE;
  1153. X    }
  1154. X#ifdef SUNTOOL
  1155. X    else {
  1156. X        int c = confirm(panel_sw->ts_windowfd);
  1157. X        if (lower(c) != 'y' && c != MS_LEFT)
  1158. X        overwrite = FALSE;
  1159. X    }
  1160. X#endif /* SUNTOOL */
  1161. X    if (!overwrite) {
  1162. X        print("\"%s\" unchanged.\n", tmp);
  1163. X        return -1;
  1164. X    }
  1165. X    }
  1166. X    if (!(fp = fopen(tmp, "w"))) {
  1167. X    error("Can't open %s", file);
  1168. X    return -1;
  1169. X    }
  1170. X
  1171. X    save_list("basic variable settings", set_options, "set", '=', fp);
  1172. X
  1173. X    save_list("mail headers for outgoing mail", own_hdrs, "my_hdr", 0, fp);
  1174. X
  1175. X    save_list("aliases", aliases, "alias", 0, fp);
  1176. X
  1177. X    alts(0, (char **)fp);
  1178. X
  1179. X    save_list("headers to ignore", ignore_hdr, "ignore", ' ', fp);
  1180. X
  1181. X    save_list("command abbreviations", functions, "cmd", ' ', fp);
  1182. X
  1183. X    save_list("command macros for function keys", fkeys, "fkey", ' ', fp);
  1184. X
  1185. X#ifdef CURSES
  1186. X    save_cmd("curses mode key bindings", cmd_map, "bind", 1, fp);
  1187. X#endif /* CURSES */
  1188. X
  1189. X    save_cmd("line mode mappings", line_map, "map", 0, fp);
  1190. X
  1191. X    save_cmd("composition mode mappings", bang_map, "map!", 0, fp);
  1192. X
  1193. X    fclose(fp);
  1194. X    print("All variables and options saved in %s\n", tmp);
  1195. X    return -1;
  1196. X}
  1197. X
  1198. Xsave_list(title, list, command, equals, fp)
  1199. Xstruct options *list;
  1200. Xregister char *command, *title, equals;
  1201. Xregister FILE *fp;
  1202. X{
  1203. X    register struct options *opts;
  1204. X    register char *p;
  1205. X
  1206. X    if (!list)
  1207. X    return;
  1208. X    fprintf(fp, "#\n# %s\n#\n", title);
  1209. X    for (opts = list; opts; opts = opts->next) {
  1210. X    if (list == set_options && !strcmp(opts->option, "cwd"))
  1211. X        continue; /* don't print $cwd */
  1212. X    fprintf(fp, "%s %s", command, opts->option);
  1213. X    if (opts->value && *opts->value) {
  1214. X        register char *quote;
  1215. X        if (!equals)
  1216. X        quote = NO_STRING;
  1217. X        else if (p = any(opts->value, "\"'"))
  1218. X        if (*p == '\'') quote = "\"";
  1219. X        else quote = "'";
  1220. X        else
  1221. X        if (!any(opts->value, " \t;|"))
  1222. X            quote = NO_STRING;
  1223. X        else quote = "'";
  1224. X        fputc(equals? equals: ' ', fp);
  1225. X        fprintf(fp, "%s%s%s", quote, opts->value, quote);
  1226. X    }
  1227. X    fputc('\n', fp);
  1228. X    }
  1229. X}
  1230. X
  1231. Xextern struct cmd_map map_func_names[];
  1232. X
  1233. Xsave_cmd(title, list, command, equals, fp)
  1234. Xstruct cmd_map *list;
  1235. Xregister char *command, *title;
  1236. Xregister int equals;
  1237. Xregister FILE *fp;
  1238. X{
  1239. X    register struct cmd_map *opts;
  1240. X    register char *p;
  1241. X    char buf[MAX_MACRO_LEN * 2];
  1242. X
  1243. X    if (!list)
  1244. X    return;
  1245. X    fprintf(fp, "#\n# %s\n#\n", title);
  1246. X    for (opts = list; opts; opts = opts->m_next) {
  1247. X    register char *quote;
  1248. X    if ((p = any(opts->m_str, "\"'")) && *p == '\'')
  1249. X        quote = "\"";
  1250. X    else
  1251. X        quote = "'";
  1252. X    fprintf(fp, "%s %s%s%s", command, quote,
  1253. X            ctrl_strcpy(buf, opts->m_str, TRUE), quote);
  1254. X    if (equals && map_func_names[opts->m_cmd].m_str)
  1255. X        fprintf(fp, " %s", map_func_names[opts->m_cmd].m_str);
  1256. X    if (opts->x_str && *opts->x_str) {
  1257. X        if ((p = any(opts->x_str, "\"'")) && *p == '\'')
  1258. X        quote = "\"";
  1259. X        else
  1260. X        quote = "'";
  1261. X        fprintf(fp, " %s%s%s", quote,
  1262. X            ctrl_strcpy(buf, opts->x_str, TRUE), quote);
  1263. X    }
  1264. X    fputc('\n', fp);
  1265. X    }
  1266. X}
  1267. X
  1268. X/*
  1269. X * do_alias handles aliases, header settings, functions, and fkeys.
  1270. X * since they're all handled in the same manner, the same routine is
  1271. X * used. argv[0] determines which to use.
  1272. X * alias is given here as an example
  1273. X *
  1274. X * alias           identify all aliases
  1275. X * alias name      identify alias
  1276. X * alias name arg1 arg2 arg3... -> name="arg1 arg2 arg3"; call add_option
  1277. X * unalias arg1 [arg2 arg3 ... ]        unalias args
  1278. X *
  1279. X * same is true for dealing with your own headers.
  1280. X * (also the expand command)
  1281. X * always return -1 since it has no effect on messages
  1282. X */
  1283. Xdo_alias(argc, argv)
  1284. Xregister char **argv;
  1285. X{
  1286. X    register char *cmd = *argv, *p;
  1287. X    struct options **list;
  1288. X    char firstchar = *cmd, buf[BUFSIZ];
  1289. X
  1290. X    if (argc == 0)
  1291. X    return 0 - in_pipe();
  1292. X    if (firstchar == 'u')
  1293. X    firstchar = cmd[2];
  1294. X    if (*++argv && !strcmp(*argv, "-?")) { /* doesn't apply for fkeys */
  1295. X    register char *help_str;
  1296. X    if (firstchar == 'a' || firstchar == 'e')
  1297. X        help_str = "alias";
  1298. X    else if (firstchar == 'c')
  1299. X        help_str = "cmd";
  1300. X    else if (firstchar == 'f')
  1301. X        help_str = "fkey";
  1302. X    else
  1303. X        help_str = "own_hdrs";
  1304. X    return help(0, help_str, cmd_help);
  1305. X    }
  1306. X
  1307. X    if (firstchar == 'a')
  1308. X    list = &aliases;
  1309. X    else if (firstchar == 'c')
  1310. X    list = &functions;
  1311. X    else if (firstchar == 'f')
  1312. X    list = &fkeys;
  1313. X    else
  1314. X    list = &own_hdrs;
  1315. X
  1316. X    if (*cmd == 'u') {
  1317. X    if (!*argv) {
  1318. X        print("%s what?\n", cmd);
  1319. X        return -1;
  1320. X    /* unset a list separated by spaces or ',' */
  1321. X    } else while (*argv) {
  1322. X        if (!strcmp(*argv, "*")) /* unset everything */
  1323. X        while (*list)
  1324. X            (void) un_set(list, (*list)->option);
  1325. X        else if (!un_set(list, *argv))
  1326. X        print("\"%s\" isn't set\n", *argv);
  1327. X        argv++;
  1328. X    }
  1329. X    return 0;
  1330. X    }
  1331. X
  1332. X    if (!*argv && *cmd != 'e') {
  1333. X    /* just type out all the aliases or own_hdrs */
  1334. X    (void) do_set(*list, NULL);
  1335. X    return 0;
  1336. X    }
  1337. X
  1338. X    if (*cmd == 'e') {   /* command was "expand" (aliases only) */
  1339. X    if (!*argv) {
  1340. X        print("expand which alias?\n");
  1341. X        return -1;
  1342. X    } else
  1343. X        do  {
  1344. X        print("%s: ", *argv);
  1345. X        if (p = alias_to_address(*argv))
  1346. X            print("%s\n", p);
  1347. X        } while (*++argv);
  1348. X    return 0;
  1349. X    }
  1350. X
  1351. X    /* at this point, *argv now points to a variable name ...
  1352. X     * check for hdr -- if so, *argv better end with a ':' (check *p)
  1353. X     */
  1354. X    if (list == &own_hdrs && !(p = index(*argv, ':'))) {
  1355. X    print("header labels must end with a ':' (%s)\n", *argv);
  1356. X    return -1;
  1357. X    }
  1358. X    if (!argv[1] && !index(*argv, '='))
  1359. X    if (p = do_set(*list, *argv))
  1360. X        print("%s\n", p);
  1361. X    else
  1362. X        print("%s is not set\n", *argv);
  1363. X    else {
  1364. X    char *tmpargv[2];
  1365. X    (void) argv_to_string(buf, argv);
  1366. X    if ((p = any(buf, " \t=")) && *p != '=')
  1367. X        *p = '=';
  1368. X    /* if we're setting an alias, enforce the insertion of commas
  1369. X     * between each well-formed address.
  1370. X     */
  1371. X    if (list == &aliases)
  1372. X        fix_up_addr(p+1);
  1373. X    tmpargv[0] = buf;
  1374. X    tmpargv[1] = NULL;
  1375. X    (void) add_option(list, tmpargv);
  1376. X    }
  1377. X    return 0;
  1378. X}
  1379. END_OF_FILE
  1380. if test 18443 -ne `wc -c <'setopts.c'`; then
  1381.     echo shar: \"'setopts.c'\" unpacked with wrong size!
  1382. fi
  1383. # end of 'setopts.c'
  1384. fi
  1385. echo shar: End of archive 8 \(of 19\).
  1386. cp /dev/null ark8isdone
  1387. MISSING=""
  1388. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1389.     if test ! -f ark${I}isdone ; then
  1390.     MISSING="${MISSING} ${I}"
  1391.     fi
  1392. done
  1393. if test "${MISSING}" = "" ; then
  1394.     echo You have unpacked all 19 archives.
  1395.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1396. else
  1397.     echo You still need to unpack the following archives:
  1398.     echo "        " ${MISSING}
  1399. fi
  1400. ##  End of shell archive.
  1401. exit 0
  1402.